package com.edoomath.api.web.controller.course;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.utils.JsonUtils;
import com.edoomath.api.entity.SigninRequest;
import com.edoomath.api.handler.QiniuHandler;
import com.edoomath.api.servcice.CourseItemService;
import com.edoomath.api.servcice.UserCourseItemExamService;
import com.edoomath.api.servcice.UserCourseItemService;
import com.edoomath.api.servcice.UserCourseService;
import com.edoomath.api.servcice.UserService;
import com.edoomath.entity.course.Course;
import com.edoomath.entity.course.CourseItem;
import com.edoomath.entity.course.CourseItemStat;
import com.edoomath.entity.course.CourseMaterail;
import com.edoomath.entity.course.UserCourseTaskMedia;
import com.edoomath.entity.user.UserSource;
import com.edoomath.entity.user.WechatOpenid;
import com.edoomath.entity.usercourse.UserCourse;
import com.edoomath.entity.usercourse.UserCourseItem;
import com.edoomath.entity.usercourse.UserCourseItemExam;
import com.edoomath.entity.usercourse.UserCourseStat;
import com.edoomath.entity.usercourse.UserCourseTask;

/**
 * 
 * @author mohanlan
 *
 */
@RequestMapping("/user-course-items")
@Controller
public class UserCourseItemController {
	
	private static final Logger logger = LoggerFactory.getLogger(UserCourseItemController.class);
	
	@Value("#{config['site.host']}")
    private String siteHost;
	
	@Autowired
	private QiniuHandler qiniuHandler;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private UserCourseService userCourseService;
	
	@Autowired
	private CourseItemService courseItemService;
	
	@Autowired
	private UserCourseItemService userCourseItemService;
	
	@Autowired
	private UserCourseItemExamService userCourseItemExamService;
	
	/**
     * 
     * @param id
     * @param unionid
     * @return
     */
    @SuppressWarnings("unchecked")
	@RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult loadCourseItem(@PathVariable(value = "id") Long id,
    							     @RequestParam(value = "unionid") String unionid) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            // 1. course-item information
            UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
            CourseItem courseItem = userCourseItem.getCourseItem();
            Course course = courseItem.getCourse();
            
            CourseItemStat courseItemStat = courseItemService.loadCourseItemStat(courseItem);
            
            List<UserCourseItemExam> exams = userCourseItemExamService.listSignedExam(userCourseItem);
            List<CourseMaterail> examMaterials = CollectionUtils.extractPropertyList(exams, "materail");
            
            
            
            return httpResult.success().data("userCourseItem", userCourseItem)
            						   .data("courseItem", courseItem)
                                       .data("course", course)
                                       .data("courseItemStat", courseItemStat)
                                       .data("exams", exams)
                                       .data("examMaterials", examMaterials)
                                       .message("获取课程信息成功");
            
        } catch (Exception e) {
            logger.error("load course item failed with error", e);
            return httpResult.fail("500").message("获取课程信息失败");
        }
        
    }
    
    /**
     * 
     * @param id
     * @param types
     * @param unionid
     * @return
     */
    @RequestMapping(value = "/{id}/tasks", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult listCourseItemTasks(@PathVariable(value = "id") Long id,
    								 	  @RequestParam(value = "type") List<String> types,
    								 	  @RequestParam(value = "unionid") String unionid) {
    	
    	HttpResult httpResult = new HttpResult();
    	
    	try {
    		
    		// 1. course-item information
            UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
            CourseItem courseItem = userCourseItem.getCourseItem();
            
            
            List<UserCourseTask> tasks = courseItemService.listCourseTask(userCourseItem);
            Map<String, UserCourseTask> tasksMap = CollectionUtils.constructMapValue(tasks, "materail.id");
            
            List<CourseMaterail> materials = courseItemService.listCourseMaterial(courseItem, types);
            Map<String, List<CourseMaterail>> result = CollectionUtils.constructMapValues(materials, "type");
            
            List<CourseMaterail> extraTaskMaterial = new ArrayList<CourseMaterail>();
            for(UserCourseTask task : tasks) {
            	if(task.isExtra()) {
            		extraTaskMaterial.add(task.getMaterail());
            	}
            }
            
            List<CourseMaterail> exerciseMaterials = result.get("EXERCISES");
            exerciseMaterials.addAll(extraTaskMaterial);
            result.put("EXERCISES", exerciseMaterials);
            
            return httpResult.success()
            				 .data("courseMaterails", result)
            				 .data("tasks", tasksMap)
            				 .message("获取资料信息成功");
    		
    	} catch (Exception e) {
            logger.error("load course item failed with error", e);
            return httpResult.fail("500").message("获取课程信息失败");
        }
    	
    }
    
    /**
     * 
     * @param id
     * @param taskId
     * @return
     */
    @RequestMapping(value = "/{id}/tasks/{taskId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult loadCourseTask(@PathVariable(value = "id") Long id,
    								 @PathVariable(value = "taskId") Long taskId) {
    	
    	HttpResult httpResult = new HttpResult();
    	
    	try {
    		
    		// 1. course-item information
            UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
            UserCourseTask task = userCourseItemService.loadTask(taskId);
            
            List<UserCourseTaskMedia> medias = userCourseItemService.listMedias(task);
            Map<String, List<UserCourseTaskMedia>> mediasMap = CollectionUtils.constructMapValues(medias, "mediaType"); 
            
            return httpResult.success().data("task", task)
            						   .data("medias", mediasMap)
            						   .data("material", task.getMaterail())
            						   .data("userCourseItem", userCourseItem);

            
    		
    	} catch (Exception e) {
            logger.error("load course item failed with error", e);
            return httpResult.fail("500").message("获取课程信息失败");
        }    
	}
    
    /**
     * 
     * @param id
     * @param taskId
     * @param images
     * @param times
     * @param voice
     * @param voiceSeconds
     * @param unionid
     * @param openid
     * @param formId
     * @return
     */
    @RequestMapping(value = "/{id}/tasks/{taskId}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult signinTask(@PathVariable(value = "id") Long id,
			 					 @PathVariable(value = "taskId") Long taskId,
			 					 @RequestParam("images") List<String> images,
			 					 @RequestParam(value = "times", required = false) String times,
			 					 @RequestParam(value = "voice", required = false) String voice,
			 					 @RequestParam(value = "voiceSeconds", required = false) Integer voiceSeconds,
			 					 @RequestParam(value = "unionid", required = false) String unionid,
			 					 @RequestParam(value = "openid", required = false) String openid,
			 					 @RequestParam(value = "formId", required = false) String formId) {
    	
    	HttpResult httpResult = new HttpResult();
    	
    	if(StringUtils.isNotBlank(openid) && StringUtils.isNotBlank(unionid)) {
    		WechatOpenid wechatOpenid = userService.loadWechatOpenid(unionid, UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		if(wechatOpenid == null) {
    			userService.saveWechatOpenid(unionid, openid, UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		}
    	}
    	
    	// 1. course-item information
        UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
        UserCourseTask task = userCourseItemService.loadTask(taskId);
        

		UserCourseStat userCourseStat = userCourseService.loadStat(userCourseItem.getUserCourse());
		
        userCourseItemService.signin(userCourseStat, userCourseItem, task, images, voice, times, voiceSeconds, formId);
    	
    	return httpResult.success().message("签到成功");
    }
    
    /**
     * 
     * @param id
     * @param requestBody
     * @return
     */
    @RequestMapping(value = "/{id}/tasks/{taskId}/new-signin", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult signinTask(@PathVariable(value = "id") Long id,
    							 @PathVariable(value = "taskId") Long taskId,
			 					 @RequestBody String requestBody) {
    	
    	HttpResult httpResult = new HttpResult();
    	logger.info("signTask with request body [{}]", requestBody);
    	
    	SigninRequest signinRequest = JsonUtils.parse(requestBody, SigninRequest.class);
    	logger.info("signTask with signinRequest body [{}]", JsonUtils.toJson(signinRequest));
    	
    	if(StringUtils.isNotBlank(signinRequest.getOpenid()) && StringUtils.isNotBlank(signinRequest.getUnionid())) {
    		WechatOpenid wechatOpenid = userService.loadWechatOpenid(signinRequest.getUnionid(), UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		if(wechatOpenid == null) {
    			userService.saveWechatOpenid(signinRequest.getUnionid(), signinRequest.getOpenid(), UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		}
    	}
    	
    	// 1. course-item information
        UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
        UserCourseTask task = userCourseItemService.loadTask(taskId);
        

		UserCourseStat userCourseStat = userCourseService.loadStat(userCourseItem.getUserCourse());
		
        userCourseItemService.signin(userCourseStat, userCourseItem, task, signinRequest);
    	
    	return httpResult.success().message("签到成功");
    }
    
    /**
     * 
     * @param id
     * @param taskId
     * @param images
     * @param times
     * @param voice
     * @return
     */
    @RequestMapping(value = "/{id}/tasks/{taskId}/re-signin", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult reSigninTask(@PathVariable(value = "id") Long id,
			 					 @PathVariable(value = "taskId") Long taskId,
			 					 @RequestParam("images") List<String> images,
			 					 @RequestParam(value = "times", required = false) String times,
			 					 @RequestParam(value = "voice", required = false) String voice,
			 					 @RequestParam(value = "voiceSeconds", required = false) Integer voiceSeconds,
			 					 @RequestParam(value = "unionid", required = false) String unionid,
			 					 @RequestParam(value = "openid", required = false) String openid,
			 					 @RequestParam(value = "formId", required = false) String formId) {
    	
    	HttpResult httpResult = new HttpResult();
    	
    	if(StringUtils.isNotBlank(openid) && StringUtils.isNotBlank(unionid)) {
    		WechatOpenid wechatOpenid = userService.loadWechatOpenid(unionid, UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		if(wechatOpenid == null) {
    			userService.saveWechatOpenid(unionid, openid, UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		}
    	}
    	
    	// 1. course-item information
        UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
        UserCourseTask task = userCourseItemService.loadTask(taskId);
        

		UserCourseStat userCourseStat = userCourseService.loadStat(userCourseItem.getUserCourse());
		
        userCourseItemService.reSignin(userCourseStat, userCourseItem, task, images, voice, times, voiceSeconds, formId);
    	
    	return httpResult.success().message("签到成功");
    }
    
    /**
     * 
     * @param id
     * @param taskId
     * @param requestBody
     * @return
     */
    @RequestMapping(value = "/{id}/tasks/{taskId}/new-resignin", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult reSigninTask(@PathVariable(value = "id") Long id,
    							   @PathVariable(value = "taskId") Long taskId,
			 					   @RequestBody String requestBody) {
    	
    	HttpResult httpResult = new HttpResult();
    	logger.info("signTask with request body [{}]", requestBody);
    	
    	SigninRequest signinRequest = JsonUtils.parse(requestBody, SigninRequest.class);
    	logger.info("signTask with signinRequest body [{}]", JsonUtils.toJson(signinRequest));
    	
    	if(StringUtils.isNotBlank(signinRequest.getOpenid()) && StringUtils.isNotBlank(signinRequest.getUnionid())) {
    		WechatOpenid wechatOpenid = userService.loadWechatOpenid(signinRequest.getUnionid(), UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		if(wechatOpenid == null) {
    			userService.saveWechatOpenid(signinRequest.getUnionid(), signinRequest.getOpenid(), UserSource.EDOOMATH_WEAPP_ACCOUNT);
    		}
    	}
    	
    	// 1. course-item information
        UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
        UserCourseTask task = userCourseItemService.loadTask(taskId);
        

		UserCourseStat userCourseStat = userCourseService.loadStat(userCourseItem.getUserCourse());
		
        userCourseItemService.signin(userCourseStat, userCourseItem, task, signinRequest);
    	
    	return httpResult.success().message("签到成功");
    }
    
    
    /**
     * 
     * @param id
     * @param taskId
     * @return
     */
    @RequestMapping(value = "/{id}/tasks/{taskId}/share", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public HttpResult share(@PathVariable(value = "id") Long id,
    						@PathVariable(value = "taskId") Long taskId) {
    	
    	HttpResult httpResult = new HttpResult();
    	
    	try {
    		
    		// 1. course-item information
            UserCourseItem userCourseItem = userCourseItemService.load(UserCourseItem.class, id);
            UserCourseTask task = userCourseItemService.loadTask(taskId);
            
            // 2. couese stat info
            UserCourse userCourse = task.getUserCourse();
            UserCourseStat userCourseStat = userCourseService.loadStat(userCourse);
            
            // 3. generate share link
            String shareLink = qiniuHandler.generateQrCode(siteHost + "/course-tasks?taskid=" + task.getId() + "&unionid=" + userCourse.getUnionid());
            
            return httpResult.success().data("task", task)
            						   .data("material", task.getMaterail())
            						   .data("userCourse", userCourse)
            						   .data("userCourseStat", userCourseStat)
            						   .data("shareLink", shareLink)
            						   .data("course", userCourse.getCourse())
            						   .data("userCourseItem", userCourseItem);

            
    		
    	} catch (Exception e) {
            logger.error("load course item failed with error", e);
            return httpResult.fail("500").message("获取课程信息失败");
    	}
    	
    }
    		
	
	
}
